package com.ease.model.util;

import oracle.spatial.geometry.JGeometry;
import oracle.sql.STRUCT;

import com.ease.common.util.Assertion;
import com.ease.model.constant.SpatialDimension;
import com.ease.model.constant.Srid;
import com.ease.model.type.GeoLine;
import com.ease.model.type.GeoPoint;
import com.ease.model.type.GeoPolygon;

/**
 * 张培云 22:15:48 OracleSpatialGeometryUtil.java里 WGS_84(srid)可以通过sql查询到,如 select srid into v_srid from
 * sde.st_geometry_columns where owner=user and table_name=upper(p_featureclassName) and column_name=upper(p_colName);
 * 
 * 另外, featureclass的objectid对应的sequence可以通过： select 'r'||registration_id into v_sequenceName from sde.table_registry
 * where owner=user and table_name = upper(p_featureclassName);
 * 
 * 
 * 
 * @author nathanleewei
 * 
 * 
 */
public abstract class OracleSpatialGeometryUtil extends Srid {

	public static JGeometry fromGeoPoint(GeoPoint geoPoint) {

		Assertion.notNull(geoPoint, "geoLine not found");

		if (null != geoPoint) {
			if (3 == SpatialDimension.DIMENSIONS) {
				return new JGeometry(geoPoint.getX(), geoPoint.getY(), geoPoint.getZ(), WGS_84);
			} else {
				return new JGeometry(geoPoint.getX(), geoPoint.getY(), WGS_84);
			}
			// return new JGeometry(geoPoint.getX(), geoPoint.getY(),
			// geoPoint.getZ());
			// return JGeometry.createPoint(new
			// double[]{geoPoint.getX(),geoPoint.getY()}, null, null);
		}
		return null;
	}

	private static double[] coords(GeoLine geoLine) {
		if (null != geoLine && null != geoLine.getGeoPoints()) {
			double[] values = new double[geoLine.getGeoPoints().size() * SpatialDimension.DIMENSIONS];
			int index = 0;
			for (GeoPoint geoPoint : geoLine.getGeoPoints()) {
				values[index++] = geoPoint.getX();
				values[index++] = geoPoint.getY();
				if (3 == SpatialDimension.DIMENSIONS) {
					values[index++] = geoPoint.getZ();
				}
			}

			return values;
		}
		return null;
	}

	private static double[] coords(GeoPolygon geoPolygon) {
		if (null != geoPolygon && null != geoPolygon.getGeoPoints()) {
			double[] values = new double[geoPolygon.getGeoPoints().size() * SpatialDimension.DIMENSIONS];
			int index = 0;
			for (GeoPoint geoPoint : geoPolygon.getGeoPoints()) {
				values[index++] = geoPoint.getX();
				values[index++] = geoPoint.getY();
				if (3 == SpatialDimension.DIMENSIONS) {
					values[index++] = geoPoint.getZ();
				}
			}

			return values;
		}
		return null;
	}

	public static JGeometry fromGeoLine(GeoLine geoLine) {

		Assertion.notNull(geoLine, "geoLine not found");
		Assertion.notEmpty(geoLine.getGeoPoints(), "geoLine not found ");
		return JGeometry.createLinearLineString(coords(geoLine), SpatialDimension.DIMENSIONS, WGS_84);
		// return new JGeometry(geoPoint.getX(), geoPoint.getY(),
		// geoPoint.getZ(), geoPoint.getSrid());
		// return new JGeometry(geoPoint.getX(), geoPoint.getY(),
		// geoPoint.getZ());
		// return JGeometry.createPoint(new
		// double[]{geoPoint.getX(),geoPoint.getY()}, null, null);

	}

	public static GeoPoint toGeoPoint(JGeometry geometry) {
		if (null != geometry) {

			double[] point = geometry.getPoint();
			if (null != point) {
				GeoPoint geoPoint = new GeoPoint();
				geoPoint.setX((point.length > 0) ? point[0] : 0);
				geoPoint.setY((point.length > 1) ? point[1] : 0);
				geoPoint.setZ((point.length > 2) ? point[2] : 0);

				// geoPoint.setSrid(geometry.getSRID());

				return geoPoint;
			}
		}
		return null;
	}

	public static GeoLine toGeoLine(JGeometry geometry) {
		if (null != geometry) {
			double[] coords = geometry.getOrdinatesArray();
			if (null != coords) {
				GeoLine geoLine = new GeoLine();
				// geoLine.setDimensions(geometry.getDimensions());
				// geoLine.setSrid(geometry.getSRID());

				// GeoPoint geoPoint = null;
				int len = coords.length / SpatialDimension.DIMENSIONS;
				for (int i = 0; i < len; i++) {
					// geoPoint = new GeoPoint();
					// geoPoint.setLongitude(coords[i * 3]);
					// geoPoint.setLatitude(coords[i * 3 + 1]);
					// geoPoint.setAltitude(coords[i * 3 + 2]);
					// geoPoint.setSrid(geometry.getSRID());
					// geoPoint.setSrid()
					if (3 == SpatialDimension.DIMENSIONS) {
						geoLine.addGeoPoint(coords[i * SpatialDimension.DIMENSIONS], coords[i * SpatialDimension.DIMENSIONS + 1], coords[i * SpatialDimension.DIMENSIONS + 2]);
					} else {
						geoLine.addGeoPoint(coords[i * SpatialDimension.DIMENSIONS], coords[i * SpatialDimension.DIMENSIONS + 1]);
					}

				}

				return geoLine;
			}
		}
		return null;
	}

	public static GeoPolygon toGeoPolygon(JGeometry geometry) {
		if (null != geometry) {
			double[] coords = geometry.getOrdinatesArray();
			if (null != coords) {
				GeoPolygon geoPolygon = new GeoPolygon();
				// geoLine.setSpatialDimension.DIMENSIONS(geometry.getSpatialDimension.DIMENSIONS());
				// geoLine.setSrid(geometry.getSRID());

				// GeoPoint geoPoint = null;
				int len = coords.length / SpatialDimension.DIMENSIONS;
				for (int i = 0; i < len; i++) {
					// geoPoint = new GeoPoint();
					// geoPoint.setLongitude(coords[i * 3]);
					// geoPoint.setLatitude(coords[i * 3 + 1]);
					// geoPoint.setAltitude(coords[i * 3 + 2]);
					// geoPoint.setSrid(geometry.getSRID());
					// geoPoint.setSrid()
					if (3 == SpatialDimension.DIMENSIONS) {
						geoPolygon.addGeoPoint(coords[i * SpatialDimension.DIMENSIONS], coords[i * SpatialDimension.DIMENSIONS + 1], coords[i * SpatialDimension.DIMENSIONS + 2]);
					} else {
						geoPolygon.addGeoPoint(coords[i * SpatialDimension.DIMENSIONS], coords[i * SpatialDimension.DIMENSIONS + 1]);
					}

				}

				return geoPolygon;
			}
		}
		return null;
	}

	public static JGeometry fromGeoPolygon(GeoPolygon geoPolygon) {
		Assertion.notNull(geoPolygon, "Geoployon not found");
		Assertion.notEmpty(geoPolygon.getGeoPoints(), "Geoployon not found ");

		return JGeometry.createLinearPolygon(coords(geoPolygon), SpatialDimension.DIMENSIONS, WGS_84);

		// return JGeometry
	}

	// http://fixunix.com/weblogic/223260-weblogic-jdbc-vendor-oracle-oraclestruct
	// -oracle-sql-struct.html
	// http://forums.oracle.com/forums/thread.jspa?messageID=3278662&
	// see http://www.hibernatespatial.org/
	public static STRUCT oracleStruct(Object object) {
		if (null != object) {

			STRUCT struct = null;

			if (object instanceof weblogic.jdbc.wrapper.Struct) {
				weblogic.jdbc.wrapper.Struct wrapperStruct = (weblogic.jdbc.wrapper.Struct) object;
				struct = (STRUCT) wrapperStruct.getVendorObj();
			} else if (object instanceof STRUCT) {
				struct = (STRUCT) object;
			} else {
				throw new RuntimeException("Failed to convert object(" + object.getClass() + ") to oracle.sql.STRUCT ");
			}
			return struct;
		}
		return null;
	}
}
